let CardType = require('./../data/CardType');

let CardController = function () {};

/**
 * 洗牌、发牌
 * @param {Array} uids 需要发牌的玩家uid数组
 * @param {Number} card_num 牌的张数
 * */
CardController.prototype.shuffle = function (uids, card_num) {
    // 1、抽牌法
    let shuffle_pick = function (m) {
        //生成m张牌
        let arr = new Array(m);
        for (let i = 0; i < m; i++) {
            arr[i] = i;
        }
        //每次抽出一张牌，放在另一堆。把最后一张未抽的牌放在空位子上。
        let cards = [];
        for (let i = m; i > 0;) {
            let rnd = Math.floor(Math.random() * i);
            cards.push(arr[rnd]);
            arr[rnd] = arr[--i];
        }
        return cards;
    };

    // 2、插牌法
    let shuffle_insert = function (m) {
        //每次生成一张最大的牌，与随机的某张牌换位子
        let arr = new Array(m);
        arr[0] = 0;
        for (let i = 1; i < m; i++) {
            let rnd = Math.floor(Math.random() * (i + 1));
            arr[i] = arr[rnd];
            arr[rnd] = i;
        }
        return arr;
    };

    // 3、换牌法
    let shuffle_swap = function (m) {
        //生成m张牌
        let arr = new Array(m);
        for (let i = 0; i < m; i++) {
            arr[i] = i;
        }
        //第i张与任意一张牌换位子，换完一轮即可
        for (let i = 0; i < m; i++) {
            let rnd = Math.floor(Math.random() * (i + 1)),
                temp = arr[rnd];
            arr[rnd] = arr[i];
            arr[i] = temp;
        }
        return arr;
    };

    let shuffleCards = shuffle_pick(52);

    let uid2cards = {};
    for (let i = 0; i < uids.length; i++) {
        uid2cards[uids[i]] = [];
        for (let j = 0; j < card_num; j++) {
            uid2cards[uids[i]].push(shuffleCards.shift());
        }
    }

    let obj = {};
    for (let uid in uid2cards) {
        obj[uid] = this._generateCardsObject(uid2cards[uid]);
    }
    return obj;
    // return uid2cards;
};

CardController.prototype.pkCards = function (cardList1, cardList2) {
    let Card = function (id) {
        let color = Math.floor(id / 13);
        let value = id % 13;
        return {
            color: color,
            value: value,
            sort: 13 - value,
            des: ['黑桃', '红桃', '梅花', '方块'][color] + ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'][value]
        };
    };
    let isDouble = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            let value = cardList[i].value;
            map[value] = true;
        }
        if (Object.keys(map).length === 2) {
            return true;
        }
        return false;
    };
    let isChain = function (cardList) {
        let values = [];
        for (let i = 0; i < cardList.length; i++) {
            values.push(cardList[i].value);
        }
        values.sort(function (a, b) {
            return a - b;
        });
        if (values[0] + 1 === values[1] && values[1] + 1 === values[2]) {
            return true;
        }
        return false;
    };
    let isSameColor = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            map[cardList[i].color] = true;
        }
        return Object.keys(map).length === 1;
    };
    let isSameColorChain = function (cardList) {
        if (isSameColor(cardList) && isChain(cardList)) {
            return true;
        }
        return false;
    };
    let isBoss = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            map[cardList[i].value] = true;
        }
        return Object.keys(map).length === 1;
    };
    for (let i = 0; i < 3; i++) {
        cardList1[i] = Card(cardList1[i]);
        cardList2[i] = Card(cardList2[i]);
    }
    let checkFuntion = {
        isDouble: isDouble,
        isChain: isChain,
        isSameColor: isSameColor,
        isSameColorChain: isSameColorChain,
        isBoss: isBoss
    };
    let CardType = {
        Single: 0,
        Double: 1,
        Chain: 2,
        SameColor: 3,
        SameColorChain: 4,
        Boss: 5
    };
    let checkResult = {
        isSingle: CardType.Single,
        isDouble: CardType.Double,
        isChain: CardType.Chain,
        isSameColor: CardType.SameColor,
        isSameColorChain: CardType.SameColorChain,
        isBoss: CardType.Boss
    };
    let sortCard = function (cards) {
        if (isDouble(cards)) {
            let map = {};
            for (let i = 0; i < cards.length; i++) {
                let card = cards[i];
                if (map.hasOwnProperty(card.value)) {
                    map[card.value].push(card);
                } else {
                    map[card.value] = [card];
                }
            }
            let singleValue = 0;
            for (let value in map) {
                if (map[value].length === 1) {
                    singleValue = parseInt(value);
                }
            }
            cards.sort(function (a, b) {
                return a.value === singleValue;
            });
        } else {
            cards.sort(function (a, b) {
                return a.value > b.value;
            });
        }
        return cards;
    };
    let result = {0: CardType.Single, 1: CardType.Single};
    let getResult = function (cardList1, cardList2) {
        let cards = [cardList1, cardList2];
        for (let i = 0; i < 2; i++) {
            for (let key in checkFuntion) {
                if (checkFuntion[key](cards[i])) {
                    result[i] = checkResult[key];
                }
            }
        }
        cardList1 = sortCard(cardList1);
        cardList2 = sortCard(cardList2);
        if (result[0] === result[1]) {
            switch (result[0]) {
                case CardType.Single:
                    // 单牌只比较牌面值(value)，不比较花色(color)
                    return cardList1[2].value > cardList2[2].value;
                    break;
                case CardType.Double:
                    // 先比对子牌、再比单牌
                    if (cardList1[0].value === cardList2[0].value) {
                        return cardList1[2] > cardList2[2];
                    }
                    return cardList1[0].value > cardList2[0].value;
                    break;
                case CardType.Chain:
                    // 只比最大或最小的牌
                    if (cardList1[0].value === cardList2[0].value) {
                        return cardList1[2].color < cardList2[2].color;
                    }
                    return cardList1[0].value > cardList2[0].value;
                    break;
                case CardType.SameColor:
                    if (cardList1[0].color === cardList2[0].color) {
                        return cardList1[0].value > cardList2[0].value;
                    }
                    return cardList1[0].color < cardList2[0].color;
                    break;
                case CardType.SameColorChain:
                    return cardList1[0].value < cardList2[0].value;
                    break;
                case CardType.Boss:
                    return cardList1[0].value > cardList2[0].value;
                    break;
                default:
                    break;
            }
        }
        return result[0] > result[1];
    };
    let pkResult = {};
    pkResult.card_type = result;
    pkResult.iswin = getResult(cardList1, cardList2);
    return pkResult;
};

/**
 * 生成炸金花手牌对象
 * @param {Array} cards 牌id数组
 * @return {Object}
 * */
CardController.prototype._generateCardsObject = function (cards) {
    let isDouble = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            let value = cardList[i].value;
            map[value] = true;
        }
        if (Object.keys(map).length === 2) {
            return true;
        }
        return false;
    };
    let isChain = function (cardList) {
        let values = [];
        for (let i = 0; i < cardList.length; i++) {
            values.push(cardList[i].value);
        }
        values.sort(function (a, b) {
            return a - b;
        });
        if (values[0] + 1 === values[1] && values[1] + 1 === values[2]) {
            return true;
        }
        return false;
    };
    let isSameColor = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            map[cardList[i].color] = true;
        }
        return Object.keys(map).length === 1;
    };
    let isSameColorChain = function (cardList) {
        if (isSameColor(cardList) && isChain(cardList)) {
            return true;
        }
        return false;
    };
    let isBoss = function (cardList) {
        let map = {};
        for (let i = 0; i < cardList.length; i++) {
            map[cardList[i].value] = true;
        }
        return Object.keys(map).length === 1;
    };

    // 1、首先获得牌的基础数据
    let card_obj = [];
    for (let i = 0; i < cards.length; i++) {
        card_obj.push(this.Card(cards[i]));
    }

    // 2、判断牌的类型
    // 2.1、检测牌型的结果
    let checkResult = {
        isSingle: CardType.Single,
        isDouble: CardType.Double,
        isChain: CardType.Chain,
        isSameColor: CardType.SameColor,
        isSameColorChain: CardType.SameColorChain,
        isBoss: CardType.Boss
    };
    // 2.2、检查函数
    let checkFuntion = {
        isDouble: isDouble,
        isChain: isChain,
        isSameColor: isSameColor,
        isSameColorChain: isSameColorChain,
        isBoss: isBoss
    };

    let obj = {
        card_array: cards,
        card_obj: card_obj,
        card_type: CardType.Single,
        card_type_des: ['特殊', '高牌', '对子', '顺子', '金花', '顺金', '豹子'][CardType.Single]
    };
    for (let check_key in checkFuntion) {
        if (checkFuntion[check_key](card_obj)) {
            obj.card_type = checkResult[check_key];
            obj.card_type_des = ['特殊', '高牌', '对子', '顺子', '金花', '顺金', '豹子'][checkResult[check_key]];
            break;
        }
    }


    return obj;
};

/**
 * 每一张牌的数据
 * @return {Object}
 * */
CardController.prototype.Card = function (id) {
    let color = Math.floor(id / 13);
    let value = id % 13;
    return {
        id: id,
        value: value,
        color: color,
        sort: 13 - value,
        des: ['黑桃', '红桃', '梅花', '方块'][color] + ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'][value]
    };
};

module.exports = CardController;